/***************************************************************************
 * memhack.cpp
 * Copyright (C) 2010  Jared Bell
 *
 * This file is part of FreeESP.
 *
 * FreeESP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FreeESP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with FreeESP.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Credits:
 * + compudaze <compudaze@gmail.com> - FreeESP author.
 * + SuperNovaAO <itshax.com> - posted his CoD6Wallhack180 source code &
 *   showed me how to access the console.
 * + R3B3L <gamedeception.net forums> - posted how to disable recoil.
 ***************************************************************************/

#include "memhack.h"

MemHack::MemHack(MemHackItemList* il) {
  memHackEnabled_ = false;
  memHackItems_ = il;
}

void MemHack::Enable() {
  if (!memHackEnabled_) {
    memHackEnabled_ = true;
    WriteMemory();
    //for (MemHackItemList::iterator it = memHackItems_->begin(); it != memHackItems_->end(); ++it) {
    //  WriteMemory(it->address(),
    //              &it->hackedBytes().front(),
    //              it->hackedBytes().size());
    //}
  }
}

void MemHack::Disable() {
  if (memHackEnabled_) {
    memHackEnabled_ = false;
    WriteMemory();
    //for (MemHackItemList::iterator it = memHackItems_->begin(); it != memHackItems_->end(); ++it) {
    //  WriteMemory(it->address(),
    //              &it->originalBytes().front(),
    //              it->originalBytes().size());
    //}
  }
}

void MemHack::Toggle() {
  if (memHackEnabled_) {
    Disable();
  } else {
    Enable();
  }
}

bool MemHack::IsEnabled() {
  return memHackEnabled_;
}

//void MemHack::WriteMemory(DWORD address, void* bytes, DWORD size) {
//  DWORD oldProtect = 0;
//  VirtualProtect((void*)address, size, PAGE_EXECUTE_READWRITE, &oldProtect);
//  memcpy((void*) address, bytes, size);
//  VirtualProtect((void*)address, size, oldProtect, &oldProtect);
//}
void MemHack::WriteMemory() {
  for (MemHackItemList::iterator it = memHackItems_->begin(); it != memHackItems_->end(); ++it) {
    DWORD address = it->GetAddress();
    BYTE* bytes = &it->GetBytes(memHackEnabled_).front();
    DWORD size = it->GetBytes(memHackEnabled_).size();
    DWORD oldProtect = 0;
    VirtualProtect((void*)address, size, PAGE_EXECUTE_READWRITE, &oldProtect);
    memcpy((void*)address, (void*)bytes, size);
    VirtualProtect((void*)address, size, oldProtect, &oldProtect);
  }
}